home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / host_cmd.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  38KB  |  1,927 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20.  
  21. #include "quakedef.h"
  22.  
  23. extern cvar_t    pausable;
  24. extern void SV_SaveSpawnparms (void);
  25.  
  26. int    current_skill;
  27.  
  28. void Mod_Print (void);
  29.  
  30. /*
  31. ==================
  32. Host_Quit_f
  33. ==================
  34. */
  35.  
  36. extern void M_Menu_Quit_f (void);
  37.  
  38. void Host_Quit_f (void)
  39. {
  40.     if (key_dest != key_console && cls.state != ca_dedicated)
  41.     {
  42.         M_Menu_Quit_f ();
  43.         return;
  44.     }
  45.     CL_Disconnect ();
  46.     Host_ShutdownServer(false);        
  47.  
  48.     Sys_Quit ();
  49. }
  50.  
  51.  
  52. /*
  53. ==================
  54. Host_Status_f
  55. ==================
  56. */
  57. void Host_Status_f (void)
  58. {
  59.     client_t    *client;
  60.     int            seconds;
  61.     int            minutes;
  62.     int            hours = 0;
  63.     int            j;
  64.     void        (*print) (char *fmt, ...);
  65.     
  66.     if (cmd_source == src_command)
  67.     {
  68.         if (!sv.active)
  69.         {
  70.             Cmd_ForwardToServer ();
  71.             return;
  72.         }
  73.         print = Con_Printf;
  74.     }
  75.     else
  76.         print = SV_ClientPrintf;
  77.  
  78.     print ("host:    %s\n", Cvar_VariableString ("hostname"));
  79.     print ("version: %4.2f\n", VERSION);
  80.     if (tcpipAvailable)
  81.         print ("tcp/ip:  %s\n", my_tcpip_address);
  82.     if (ipxAvailable)
  83.         print ("ipx:     %s\n", my_ipx_address);
  84.     print ("map:     %s\n", sv.name);
  85.     print ("players: %i active (%i max)\n\n", net_activeconnections, svs.maxclients);
  86.     for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
  87.     {
  88.         if (!client->active)
  89.             continue;
  90.         seconds = (int)(net_time - client->netconnection->connecttime);
  91.         minutes = seconds / 60;
  92.         if (minutes)
  93.         {
  94.             seconds -= (minutes * 60);
  95.             hours = minutes / 60;
  96.             if (hours)
  97.                 minutes -= (hours * 60);
  98.         }
  99.         else
  100.             hours = 0;
  101.         print ("#%-2u %-16.16s  %3i  %2i:%02i:%02i\n", j+1, client->name, (int)client->edict->v.frags, hours, minutes, seconds);
  102.         print ("   %s\n", client->netconnection->address);
  103.     }
  104. }
  105.  
  106.  
  107. /*
  108. ==================
  109. Host_God_f
  110.  
  111. Sets client to godmode
  112. ==================
  113. */
  114. void Host_God_f (void)
  115. {
  116.     if (cmd_source == src_command)
  117.     {
  118.         Cmd_ForwardToServer ();
  119.         return;
  120.     }
  121.  
  122.     if (pr_global_struct->deathmatch && !host_client->privileged)
  123.         return;
  124.  
  125.     sv_player->v.flags = (int)sv_player->v.flags ^ FL_GODMODE;
  126.     if (!((int)sv_player->v.flags & FL_GODMODE) )
  127.         SV_ClientPrintf ("godmode OFF\n");
  128.     else
  129.         SV_ClientPrintf ("godmode ON\n");
  130. }
  131.  
  132. void Host_Notarget_f (void)
  133. {
  134.     if (cmd_source == src_command)
  135.     {
  136.         Cmd_ForwardToServer ();
  137.         return;
  138.     }
  139.  
  140.     if (pr_global_struct->deathmatch && !host_client->privileged)
  141.         return;
  142.  
  143.     sv_player->v.flags = (int)sv_player->v.flags ^ FL_NOTARGET;
  144.     if (!((int)sv_player->v.flags & FL_NOTARGET) )
  145.         SV_ClientPrintf ("notarget OFF\n");
  146.     else
  147.         SV_ClientPrintf ("notarget ON\n");
  148. }
  149.  
  150. qboolean noclip_anglehack;
  151.  
  152. void Host_Noclip_f (void)
  153. {
  154.     if (cmd_source == src_command)
  155.     {
  156.         Cmd_ForwardToServer ();
  157.         return;
  158.     }
  159.  
  160.     if (pr_global_struct->deathmatch && !host_client->privileged)
  161.         return;
  162.  
  163.     if (sv_player->v.movetype != MOVETYPE_NOCLIP)
  164.     {
  165.         noclip_anglehack = true;
  166.         sv_player->v.movetype = MOVETYPE_NOCLIP;
  167.         SV_ClientPrintf ("noclip ON\n");
  168.     }
  169.     else
  170.     {
  171.         noclip_anglehack = false;
  172.         sv_player->v.movetype = MOVETYPE_WALK;
  173.         SV_ClientPrintf ("noclip OFF\n");
  174.     }
  175. }
  176.  
  177. /*
  178. ==================
  179. Host_Fly_f
  180.  
  181. Sets client to flymode
  182. ==================
  183. */
  184. void Host_Fly_f (void)
  185. {
  186.     if (cmd_source == src_command)
  187.     {
  188.         Cmd_ForwardToServer ();
  189.         return;
  190.     }
  191.  
  192.     if (pr_global_struct->deathmatch && !host_client->privileged)
  193.         return;
  194.  
  195.     if (sv_player->v.movetype != MOVETYPE_FLY)
  196.     {
  197.         sv_player->v.movetype = MOVETYPE_FLY;
  198.         SV_ClientPrintf ("flymode ON\n");
  199.     }
  200.     else
  201.     {
  202.         sv_player->v.movetype = MOVETYPE_WALK;
  203.         SV_ClientPrintf ("flymode OFF\n");
  204.     }
  205. }
  206.  
  207.  
  208. /*
  209. ==================
  210. Host_Ping_f
  211.  
  212. ==================
  213. */
  214. void Host_Ping_f (void)
  215. {
  216.     int        i, j;
  217.     float    total;
  218.     client_t    *client;
  219.     
  220.     if (cmd_source == src_command)
  221.     {
  222.         Cmd_ForwardToServer ();
  223.         return;
  224.     }
  225.  
  226.     SV_ClientPrintf ("Client ping times:\n");
  227.     for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
  228.     {
  229.         if (!client->active)
  230.             continue;
  231.         total = 0;
  232.         for (j=0 ; j<NUM_PING_TIMES ; j++)
  233.             total+=client->ping_times[j];
  234.         total /= NUM_PING_TIMES;
  235.         SV_ClientPrintf ("%4i %s\n", (int)(total*1000), client->name);
  236.     }
  237. }
  238.  
  239. /*
  240. ===============================================================================
  241.  
  242. SERVER TRANSITIONS
  243.  
  244. ===============================================================================
  245. */
  246.  
  247.  
  248. /*
  249. ======================
  250. Host_Map_f
  251.  
  252. handle a 
  253. map <servername>
  254. command from the console.  Active clients are kicked off.
  255. ======================
  256. */
  257. void Host_Map_f (void)
  258. {
  259.     int        i;
  260.     char    name[MAX_QPATH];
  261.  
  262.     if (cmd_source != src_command)
  263.         return;
  264.  
  265.     cls.demonum = -1;        // stop demo loop in case this fails
  266.  
  267.     CL_Disconnect ();
  268.     Host_ShutdownServer(false);        
  269.  
  270.     key_dest = key_game;            // remove console or menu
  271.     SCR_BeginLoadingPlaque ();
  272.  
  273.     cls.mapstring[0] = 0;
  274.     for (i=0 ; i<Cmd_Argc() ; i++)
  275.     {
  276.         strcat (cls.mapstring, Cmd_Argv(i));
  277.         strcat (cls.mapstring, " ");
  278.     }
  279.     strcat (cls.mapstring, "\n");
  280.  
  281.     svs.serverflags = 0;            // haven't completed an episode yet
  282.     strcpy (name, Cmd_Argv(1));
  283. #ifdef QUAKE2
  284.     SV_SpawnServer (name, NULL);
  285. #else
  286.     SV_SpawnServer (name);
  287. #endif
  288.     if (!sv.active)
  289.         return;
  290.     
  291.     if (cls.state != ca_dedicated)
  292.     {
  293.         strcpy (cls.spawnparms, "");
  294.  
  295.         for (i=2 ; i<Cmd_Argc() ; i++)
  296.         {
  297.             strcat (cls.spawnparms, Cmd_Argv(i));
  298.             strcat (cls.spawnparms, " ");
  299.         }
  300.         
  301.         Cmd_ExecuteString ("connect local", src_command);
  302.     }    
  303. }
  304.  
  305. /*
  306. ==================
  307. Host_Changelevel_f
  308.  
  309. Goes to a new map, taking all clients along
  310. ==================
  311. */
  312. void Host_Changelevel_f (void)
  313. {
  314. #ifdef QUAKE2
  315.     char    level[MAX_QPATH];
  316.     char    _startspot[MAX_QPATH];
  317.     char    *startspot;
  318.  
  319.     if (Cmd_Argc() < 2)
  320.     {
  321.         Con_Printf ("changelevel <levelname> : continue game on a new level\n");
  322.         return;
  323.     }
  324.     if (!sv.active || cls.demoplayback)
  325.     {
  326.         Con_Printf ("Only the server may changelevel\n");
  327.         return;
  328.     }
  329.  
  330.     strcpy (level, Cmd_Argv(1));
  331.     if (Cmd_Argc() == 2)
  332.         startspot = NULL;
  333.     else
  334.     {
  335.         strcpy (_startspot, Cmd_Argv(2));
  336.         startspot = _startspot;
  337.     }
  338.  
  339.     SV_SaveSpawnparms ();
  340.     SV_SpawnServer (level, startspot);
  341. #else
  342.     char    level[MAX_QPATH];
  343.  
  344.     if (Cmd_Argc() != 2)
  345.     {
  346.         Con_Printf ("changelevel <levelname> : continue game on a new level\n");
  347.         return;
  348.     }
  349.     if (!sv.active || cls.demoplayback)
  350.     {
  351.         Con_Printf ("Only the server may changelevel\n");
  352.         return;
  353.     }
  354.     SV_SaveSpawnparms ();
  355.     strcpy (level, Cmd_Argv(1));
  356.     SV_SpawnServer (level);
  357. #endif
  358. }
  359.  
  360. /*
  361. ==================
  362. Host_Restart_f
  363.  
  364. Restarts the current server for a dead player
  365. ==================
  366. */
  367. void Host_Restart_f (void)
  368. {
  369.     char    mapname[MAX_QPATH];
  370. #ifdef QUAKE2
  371.     char    startspot[MAX_QPATH];
  372. #endif
  373.  
  374.     if (cls.demoplayback || !sv.active)
  375.         return;
  376.  
  377.     if (cmd_source != src_command)
  378.         return;
  379.     strcpy (mapname, sv.name);    // must copy out, because it gets cleared
  380.                                 // in sv_spawnserver
  381. #ifdef QUAKE2
  382.     strcpy(startspot, sv.startspot);
  383.     SV_SpawnServer (mapname, startspot);
  384. #else
  385.     SV_SpawnServer (mapname);
  386. #endif
  387. }
  388.  
  389. /*
  390. ==================
  391. Host_Reconnect_f
  392.  
  393. This command causes the client to wait for the signon messages again.
  394. This is sent just before a server changes levels
  395. ==================
  396. */
  397. void Host_Reconnect_f (void)
  398. {
  399.     SCR_BeginLoadingPlaque ();
  400.     cls.signon = 0;        // need new connection messages
  401. }
  402.  
  403. /*
  404. =====================
  405. Host_Connect_f
  406.  
  407. User command to connect to server
  408. =====================
  409. */
  410. void Host_Connect_f (void)
  411. {
  412.     char    name[MAX_QPATH];
  413.     
  414.     cls.demonum = -1;        // stop demo loop in case this fails
  415.     if (cls.demoplayback)
  416.     {
  417.         CL_StopPlayback ();
  418.         CL_Disconnect ();
  419.     }
  420.     strcpy (name, Cmd_Argv(1));
  421.     CL_EstablishConnection (name);
  422.     Host_Reconnect_f ();
  423. }
  424.  
  425.  
  426. /*
  427. ===============================================================================
  428.  
  429. LOAD / SAVE GAME
  430.  
  431. ===============================================================================
  432. */
  433.  
  434. #define    SAVEGAME_VERSION    5
  435.  
  436. /*
  437. ===============
  438. Host_SavegameComment
  439.  
  440. Writes a SAVEGAME_COMMENT_LENGTH character comment describing the current 
  441. ===============
  442. */
  443. void Host_SavegameComment (char *text)
  444. {
  445.     int        i;
  446.     char    kills[20];
  447.  
  448.     for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
  449.         text[i] = ' ';
  450.     memcpy (text, cl.levelname, strlen(cl.levelname));
  451.     sprintf (kills,"kills:%3i/%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
  452.     memcpy (text+22, kills, strlen(kills));
  453. // convert space to _ to make stdio happy
  454.     for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
  455.         if (text[i] == ' ')
  456.             text[i] = '_';
  457.     text[SAVEGAME_COMMENT_LENGTH] = '\0';
  458. }
  459.  
  460.  
  461. /*
  462. ===============
  463. Host_Savegame_f
  464. ===============
  465. */
  466. void Host_Savegame_f (void)
  467. {
  468.     char    name[256];
  469.     FILE    *f;
  470.     int        i;
  471.     char    comment[SAVEGAME_COMMENT_LENGTH+1];
  472.  
  473.     if (cmd_source != src_command)
  474.         return;
  475.  
  476.     if (!sv.active)
  477.     {
  478.         Con_Printf ("Not playing a local game.\n");
  479.         return;
  480.     }
  481.  
  482.     if (cl.intermission)
  483.     {
  484.         Con_Printf ("Can't save in intermission.\n");
  485.         return;
  486.     }
  487.  
  488.     if (svs.maxclients != 1)
  489.     {
  490.         Con_Printf ("Can't save multiplayer games.\n");
  491.         return;
  492.     }
  493.  
  494.     if (Cmd_Argc() != 2)
  495.     {
  496.         Con_Printf ("save <savename> : save a game\n");
  497.         return;
  498.     }
  499.  
  500.     if (strstr(Cmd_Argv(1), ".."))
  501.     {
  502.         Con_Printf ("Relative pathnames are not allowed.\n");
  503.         return;
  504.     }
  505.         
  506.     for (i=0 ; i<svs.maxclients ; i++)
  507.     {
  508.         if (svs.clients[i].active && (svs.clients[i].edict->v.health <= 0) )
  509.         {
  510.             Con_Printf ("Can't savegame with a dead player\n");
  511.             return;
  512.         }
  513.     }
  514.  
  515.     sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
  516.     COM_DefaultExtension (name, ".sav");
  517.     
  518.     Con_Printf ("Saving game to %s...\n", name);
  519.     f = fopen (name, "w");
  520.     if (!f)
  521.     {
  522.         Con_Printf ("ERROR: couldn't open.\n");
  523.         return;
  524.     }
  525.     
  526.     fprintf (f, "%i\n", SAVEGAME_VERSION);
  527.     Host_SavegameComment (comment);
  528.     fprintf (f, "%s\n", comment);
  529.     for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
  530.         fprintf (f, "%f\n", svs.clients->spawn_parms[i]);
  531.     fprintf (f, "%d\n", current_skill);
  532.     fprintf (f, "%s\n", sv.name);
  533.     fprintf (f, "%f\n",sv.time);
  534.  
  535. // write the light styles
  536.  
  537.     for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
  538.     {
  539.         if (sv.lightstyles[i])
  540.             fprintf (f, "%s\n", sv.lightstyles[i]);
  541.         else
  542.             fprintf (f,"m\n");
  543.     }
  544.  
  545.  
  546.     ED_WriteGlobals (f);
  547.     for (i=0 ; i<sv.num_edicts ; i++)
  548.     {
  549.         ED_Write (f, EDICT_NUM(i));
  550.         fflush (f);
  551.     }
  552.     fclose (f);
  553.     Con_Printf ("done.\n");
  554. }
  555.  
  556.  
  557. /*
  558. ===============
  559. Host_Loadgame_f
  560. ===============
  561. */
  562. void Host_Loadgame_f (void)
  563. {
  564.     char    name[MAX_OSPATH];
  565.     FILE    *f;
  566.     char    mapname[MAX_QPATH];
  567.     float    time, tfloat;
  568.     char    str[32768], *start;
  569.     int        i, r;
  570.     edict_t    *ent;
  571.     int        entnum;
  572.     int        version;
  573.     float            spawn_parms[NUM_SPAWN_PARMS];
  574.  
  575.     if (cmd_source != src_command)
  576.         return;
  577.  
  578.     if (Cmd_Argc() != 2)
  579.     {
  580.         Con_Printf ("load <savename> : load a game\n");
  581.         return;
  582.     }
  583.  
  584.     cls.demonum = -1;        // stop demo loop in case this fails
  585.  
  586.     sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
  587.     COM_DefaultExtension (name, ".sav");
  588.     
  589. // we can't call SCR_BeginLoadingPlaque, because too much stack space has
  590. // been used.  The menu calls it before stuffing loadgame command
  591. //    SCR_BeginLoadingPlaque ();
  592.  
  593.     Con_Printf ("Loading game from %s...\n", name);
  594.     f = fopen (name, "r");
  595.     if (!f)
  596.     {
  597.         Con_Printf ("ERROR: couldn't open.\n");
  598.         return;
  599.     }
  600.  
  601.     fscanf (f, "%i\n", &version);
  602.     if (version != SAVEGAME_VERSION)
  603.     {
  604.         fclose (f);
  605.         Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
  606.         return;
  607.     }
  608.     fscanf (f, "%s\n", str);
  609.     for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
  610.         fscanf (f, "%f\n", &spawn_parms[i]);
  611. // this silliness is so we can load 1.06 save files, which have float skill values
  612.     fscanf (f, "%f\n", &tfloat);
  613.     current_skill = (int)(tfloat + 0.1);
  614.     Cvar_SetValue ("skill", (float)current_skill);
  615.  
  616. #ifdef QUAKE2
  617.     Cvar_SetValue ("deathmatch", 0);
  618.     Cvar_SetValue ("coop", 0);
  619.     Cvar_SetValue ("teamplay", 0);
  620. #endif
  621.  
  622.     fscanf (f, "%s\n",mapname);
  623.     fscanf (f, "%f\n",&time);
  624.  
  625.     CL_Disconnect_f ();
  626.     
  627. #ifdef QUAKE2
  628.     SV_SpawnServer (mapname, NULL);
  629. #else
  630.     SV_SpawnServer (mapname);
  631. #endif
  632.     if (!sv.active)
  633.     {
  634.         Con_Printf ("Couldn't load map\n");
  635.         return;
  636.     }
  637.     sv.paused = true;        // pause until all clients connect
  638.     sv.loadgame = true;
  639.  
  640. // load the light styles
  641.  
  642.     for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
  643.     {
  644.         fscanf (f, "%s\n", str);
  645.         sv.lightstyles[i] = Hunk_Alloc (strlen(str)+1);
  646.         strcpy (sv.lightstyles[i], str);
  647.     }
  648.  
  649. // load the edicts out of the savegame file
  650.     entnum = -1;        // -1 is the globals
  651.     while (!feof(f))
  652.     {
  653.         for (i=0 ; i<sizeof(str)-1 ; i++)
  654.         {
  655.             r = fgetc (f);
  656.             if (r == EOF || !r)
  657.                 break;
  658.             str[i] = r;
  659.             if (r == '}')
  660.             {
  661.                 i++;
  662.                 break;
  663.             }
  664.         }
  665.         if (i == sizeof(str)-1)
  666.             Sys_Error ("Loadgame buffer overflow");
  667.         str[i] = 0;
  668.         start = str;
  669.         start = COM_Parse(str);
  670.         if (!com_token[0])
  671.             break;        // end of file
  672.         if (strcmp(com_token,"{"))
  673.             Sys_Error ("First token isn't a brace");
  674.             
  675.         if (entnum == -1)
  676.         {    // parse the global vars
  677.             ED_ParseGlobals (start);
  678.         }
  679.         else
  680.         {    // parse an edict
  681.  
  682.             ent = EDICT_NUM(entnum);
  683.             memset (&ent->v, 0, progs->entityfields * 4);
  684.             ent->free = false;
  685.             ED_ParseEdict (start, ent);
  686.     
  687.         // link it into the bsp tree
  688.             if (!ent->free)
  689.                 SV_LinkEdict (ent, false);
  690.         }
  691.  
  692.         entnum++;
  693.     }
  694.     
  695.     sv.num_edicts = entnum;
  696.     sv.time = time;
  697.  
  698.     fclose (f);
  699.  
  700.     for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
  701.         svs.clients->spawn_parms[i] = spawn_parms[i];
  702.  
  703.     if (cls.state != ca_dedicated)
  704.     {
  705.         CL_EstablishConnection ("local");
  706.         Host_Reconnect_f ();
  707.     }
  708. }
  709.  
  710. #ifdef QUAKE2
  711. void SaveGamestate()
  712. {
  713.     char    name[256];
  714.     FILE    *f;
  715.     int        i;
  716.     char    comment[SAVEGAME_COMMENT_LENGTH+1];
  717.     edict_t    *ent;
  718.  
  719.     sprintf (name, "%s/%s.gip", com_gamedir, sv.name);
  720.     
  721.     Con_Printf ("Saving game to %s...\n", name);
  722.     f = fopen (name, "w");
  723.     if (!f)
  724.     {
  725.         Con_Printf ("ERROR: couldn't open.\n");
  726.         return;
  727.     }
  728.     
  729.     fprintf (f, "%i\n", SAVEGAME_VERSION);
  730.     Host_SavegameComment (comment);
  731.     fprintf (f, "%s\n", comment);
  732. //    for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
  733. //        fprintf (f, "%f\n", svs.clients->spawn_parms[i]);
  734.     fprintf (f, "%f\n", skill.value);
  735.     fprintf (f, "%s\n", sv.name);
  736.     fprintf (f, "%f\n", sv.time);
  737.  
  738. // write the light styles
  739.  
  740.     for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
  741.     {
  742.         if (sv.lightstyles[i])
  743.             fprintf (f, "%s\n", sv.lightstyles[i]);
  744.         else
  745.             fprintf (f,"m\n");
  746.     }
  747.  
  748.  
  749.     for (i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
  750.     {
  751.         ent = EDICT_NUM(i);
  752.         if ((int)ent->v.flags & FL_ARCHIVE_OVERRIDE)
  753.             continue;
  754.         fprintf (f, "%i\n",i);
  755.         ED_Write (f, ent);
  756.         fflush (f);
  757.     }
  758.     fclose (f);
  759.     Con_Printf ("done.\n");
  760. }
  761.  
  762. int LoadGamestate(char *level, char *startspot)
  763. {
  764.     char    name[MAX_OSPATH];
  765.     FILE    *f;
  766.     char    mapname[MAX_QPATH];
  767.     float    time, sk;
  768.     char    str[32768], *start;
  769.     int        i, r;
  770.     edict_t    *ent;
  771.     int        entnum;
  772.     int        version;
  773. //    float    spawn_parms[NUM_SPAWN_PARMS];
  774.  
  775.     sprintf (name, "%s/%s.gip", com_gamedir, level);
  776.     
  777.     Con_Printf ("Loading game from %s...\n", name);
  778.     f = fopen (name, "r");
  779.     if (!f)
  780.     {
  781.         Con_Printf ("ERROR: couldn't open.\n");
  782.         return -1;
  783.     }
  784.  
  785.     fscanf (f, "%i\n", &version);
  786.     if (version != SAVEGAME_VERSION)
  787.     {
  788.         fclose (f);
  789.         Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
  790.         return -1;
  791.     }
  792.     fscanf (f, "%s\n", str);
  793. //    for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
  794. //        fscanf (f, "%f\n", &spawn_parms[i]);
  795.     fscanf (f, "%f\n", &sk);
  796.     Cvar_SetValue ("skill", sk);
  797.  
  798.     fscanf (f, "%s\n",mapname);
  799.     fscanf (f, "%f\n",&time);
  800.  
  801.     SV_SpawnServer (mapname, startspot);
  802.  
  803.     if (!sv.active)
  804.     {
  805.         Con_Printf ("Couldn't load map\n");
  806.         return -1;
  807.     }
  808.  
  809. // load the light styles
  810.     for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
  811.     {
  812.         fscanf (f, "%s\n", str);
  813.         sv.lightstyles[i] = Hunk_Alloc (strlen(str)+1);
  814.         strcpy (sv.lightstyles[i], str);
  815.     }
  816.  
  817. // load the edicts out of the savegame file
  818.     while (!feof(f))
  819.     {
  820.         fscanf (f, "%i\n",&entnum);
  821.         for (i=0 ; i<sizeof(str)-1 ; i++)
  822.         {
  823.             r = fgetc (f);
  824.             if (r == EOF || !r)
  825.                 break;
  826.             str[i] = r;
  827.             if (r == '}')
  828.             {
  829.                 i++;
  830.                 break;
  831.             }
  832.         }
  833.         if (i == sizeof(str)-1)
  834.             Sys_Error ("Loadgame buffer overflow");
  835.         str[i] = 0;
  836.         start = str;
  837.         start = COM_Parse(str);
  838.         if (!com_token[0])
  839.             break;        // end of file
  840.         if (strcmp(com_token,"{"))
  841.             Sys_Error ("First token isn't a brace");
  842.             
  843.         // parse an edict
  844.  
  845.         ent = EDICT_NUM(entnum);
  846.         memset (&ent->v, 0, progs->entityfields * 4);
  847.         ent->free = false;
  848.         ED_ParseEdict (start, ent);
  849.     
  850.         // link it into the bsp tree
  851.         if (!ent->free)
  852.             SV_LinkEdict (ent, false);
  853.     }
  854.     
  855. //    sv.num_edicts = entnum;
  856.     sv.time = time;
  857.     fclose (f);
  858.  
  859. //    for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
  860. //        svs.clients->spawn_parms[i] = spawn_parms[i];
  861.  
  862.     return 0;
  863. }
  864.  
  865. // changing levels within a unit
  866. void Host_Changelevel2_f (void)
  867. {
  868.     char    level[MAX_QPATH];
  869.     char    _startspot[MAX_QPATH];
  870.     char    *startspot;
  871.  
  872.     if (Cmd_Argc() < 2)
  873.     {
  874.         Con_Printf ("changelevel2 <levelname> : continue game on a new level in the unit\n");
  875.         return;
  876.     }
  877.     if (!sv.active || cls.demoplayback)
  878.     {
  879.         Con_Printf ("Only the server may changelevel\n");
  880.         return;
  881.     }
  882.  
  883.     strcpy (level, Cmd_Argv(1));
  884.     if (Cmd_Argc() == 2)
  885.         startspot = NULL;
  886.     else
  887.     {
  888.         strcpy (_startspot, Cmd_Argv(2));
  889.         startspot = _startspot;
  890.     }
  891.  
  892.     SV_SaveSpawnparms ();
  893.  
  894.     // save the current level's state
  895.     SaveGamestate ();
  896.  
  897.     // try to restore the new level
  898.     if (LoadGamestate (level, startspot))
  899.         SV_SpawnServer (level, startspot);
  900. }
  901. #endif
  902.  
  903.  
  904. //============================================================================
  905.  
  906. /*
  907. ======================
  908. Host_Name_f
  909. ======================
  910. */
  911. void Host_Name_f (void)
  912. {
  913.     char    *newName;
  914.  
  915.     if (Cmd_Argc () == 1)
  916.     {
  917.         Con_Printf ("\"name\" is \"%s\"\n", cl_name.string);
  918.         return;
  919.     }
  920.     if (Cmd_Argc () == 2)
  921.         newName = Cmd_Argv(1);    
  922.     else
  923.         newName = Cmd_Args();
  924.     newName[15] = 0;
  925.  
  926.     if (cmd_source == src_command)
  927.     {
  928.         if (Q_strcmp(cl_name.string, newName) == 0)
  929.             return;
  930.         Cvar_Set ("_cl_name", newName);
  931.         if (cls.state == ca_connected)
  932.             Cmd_ForwardToServer ();
  933.         return;
  934.     }
  935.  
  936.     if (host_client->name[0] && strcmp(host_client->name, "unconnected") )
  937.         if (Q_strcmp(host_client->name, newName) != 0)
  938.             Con_Printf ("%s renamed to %s\n", host_client->name, newName);
  939.     Q_strcpy (host_client->name, newName);
  940.     host_client->edict->v.netname = host_client->name - pr_strings;
  941.     
  942. // send notification to all clients
  943.     
  944.     MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
  945.     MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
  946.     MSG_WriteString (&sv.reliable_datagram, host_client->name);
  947. }
  948.  
  949.     
  950. void Host_Version_f (void)
  951. {
  952.     Con_Printf ("Version %4.2f\n", VERSION);
  953.     Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
  954. }
  955.  
  956. #ifdef IDGODS
  957. void Host_Please_f (void)
  958. {
  959.     client_t *cl;
  960.     int            j;
  961.     
  962.     if (cmd_source != src_command)
  963.         return;
  964.  
  965.     if ((Cmd_Argc () == 3) && Q_strcmp(Cmd_Argv(1), "#") == 0)
  966.     {
  967.         j = Q_atof(Cmd_Argv(2)) - 1;
  968.         if (j < 0 || j >= svs.maxclients)
  969.             return;
  970.         if (!svs.clients[j].active)
  971.             return;
  972.         cl = &svs.clients[j];
  973.         if (cl->privileged)
  974.         {
  975.             cl->privileged = false;
  976.             cl->edict->v.flags = (int)cl->edict->v.flags & ~(FL_GODMODE|FL_NOTARGET);
  977.             cl->edict->v.movetype = MOVETYPE_WALK;
  978.             noclip_anglehack = false;
  979.         }
  980.         else
  981.             cl->privileged = true;
  982.     }
  983.  
  984.     if (Cmd_Argc () != 2)
  985.         return;
  986.  
  987.     for (j=0, cl = svs.clients ; j<svs.maxclients ; j++, cl++)
  988.     {
  989.         if (!cl->active)
  990.             continue;
  991.         if (Q_strcasecmp(cl->name, Cmd_Argv(1)) == 0)
  992.         {
  993.             if (cl->privileged)
  994.             {
  995.                 cl->privileged = false;
  996.                 cl->edict->v.flags = (int)cl->edict->v.flags & ~(FL_GODMODE|FL_NOTARGET);
  997.                 cl->edict->v.movetype = MOVETYPE_WALK;
  998.                 noclip_anglehack = false;
  999.             }
  1000.             else
  1001.                 cl->privileged = true;
  1002.             break;
  1003.         }
  1004.     }
  1005. }
  1006. #endif
  1007.  
  1008.  
  1009. void Host_Say(qboolean teamonly)
  1010. {
  1011.     client_t *client;
  1012.     client_t *save;
  1013.     int        j;
  1014.     char    *p;
  1015.     unsigned char    text[64];
  1016.     qboolean    fromServer = false;
  1017.  
  1018.     if (cmd_source == src_command)
  1019.     {
  1020.         if (cls.state == ca_dedicated)
  1021.         {
  1022.             fromServer = true;
  1023.             teamonly = false;
  1024.         }
  1025.         else
  1026.         {
  1027.             Cmd_ForwardToServer ();
  1028.             return;
  1029.         }
  1030.     }
  1031.  
  1032.     if (Cmd_Argc () < 2)
  1033.         return;
  1034.  
  1035.     save = host_client;
  1036.  
  1037.     p = Cmd_Args();
  1038. // remove quotes if present
  1039.     if (*p == '"')
  1040.     {
  1041.         p++;
  1042.         p[Q_strlen(p)-1] = 0;
  1043.     }
  1044.  
  1045. // turn on color set 1
  1046.     if (!fromServer)
  1047.         sprintf (text, "%c%s: ", 1, save->name);
  1048.     else
  1049.         sprintf (text, "%c<%s> ", 1, hostname.string);
  1050.  
  1051.     j = sizeof(text) - 2 - Q_strlen(text);  // -2 for /n and null terminator
  1052.     if (Q_strlen(p) > j)
  1053.         p[j] = 0;
  1054.  
  1055.     strcat (text, p);
  1056.     strcat (text, "\n");
  1057.  
  1058.     for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++)
  1059.     {
  1060.         if (!client || !client->active || !client->spawned)
  1061.             continue;
  1062.         if (teamplay.value && teamonly && client->edict->v.team != save->edict->v.team)
  1063.             continue;
  1064.         host_client = client;
  1065.         SV_ClientPrintf("%s", text);
  1066.     }
  1067.     host_client = save;
  1068.  
  1069.     Sys_Printf("%s", &text[1]);
  1070. }
  1071.  
  1072.  
  1073. void Host_Say_f(void)
  1074. {
  1075.     Host_Say(false);
  1076. }
  1077.  
  1078.  
  1079. void Host_Say_Team_f(void)
  1080. {
  1081.     Host_Say(true);
  1082. }
  1083.  
  1084.  
  1085. void Host_Tell_f(void)
  1086. {
  1087.     client_t *client;
  1088.     client_t *save;
  1089.     int        j;
  1090.     char    *p;
  1091.     char    text[64];
  1092.  
  1093.     if (cmd_source == src_command)
  1094.     {
  1095.         Cmd_ForwardToServer ();
  1096.         return;
  1097.     }
  1098.  
  1099.     if (Cmd_Argc () < 3)
  1100.         return;
  1101.  
  1102.     Q_strcpy(text, host_client->name);
  1103.     Q_strcat(text, ": ");
  1104.  
  1105.     p = Cmd_Args();
  1106.  
  1107. // remove quotes if present
  1108.     if (*p == '"')
  1109.     {
  1110.         p++;
  1111.         p[Q_strlen(p)-1] = 0;
  1112.     }
  1113.  
  1114. // check length & truncate if necessary
  1115.     j = sizeof(text) - 2 - Q_strlen(text);  // -2 for /n and null terminator
  1116.     if (Q_strlen(p) > j)
  1117.         p[j] = 0;
  1118.  
  1119.     strcat (text, p);
  1120.     strcat (text, "\n");
  1121.  
  1122.     save = host_client;
  1123.     for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++)
  1124.     {
  1125.         if (!client->active || !client->spawned)
  1126.             continue;
  1127.         if (Q_strcasecmp(client->name, Cmd_Argv(1)))
  1128.             continue;
  1129.         host_client = client;
  1130.         SV_ClientPrintf("%s", text);
  1131.         break;
  1132.     }
  1133.     host_client = save;
  1134. }
  1135.  
  1136.  
  1137. /*
  1138. ==================
  1139. Host_Color_f
  1140. ==================
  1141. */
  1142. void Host_Color_f(void)
  1143. {
  1144.     int        top, bottom;
  1145.     int        playercolor;
  1146.     
  1147.     if (Cmd_Argc() == 1)
  1148.     {
  1149.         Con_Printf ("\"color\" is \"%i %i\"\n", ((int)cl_color.value) >> 4, ((int)cl_color.value) & 0x0f);
  1150.         Con_Printf ("color <0-13> [0-13]\n");
  1151.         return;
  1152.     }
  1153.  
  1154.     if (Cmd_Argc() == 2)
  1155.         top = bottom = atoi(Cmd_Argv(1));
  1156.     else
  1157.     {
  1158.         top = atoi(Cmd_Argv(1));
  1159.         bottom = atoi(Cmd_Argv(2));
  1160.     }
  1161.     
  1162.     top &= 15;
  1163.     if (top > 13)
  1164.         top = 13;
  1165.     bottom &= 15;
  1166.     if (bottom > 13)
  1167.         bottom = 13;
  1168.     
  1169.     playercolor = top*16 + bottom;
  1170.  
  1171.     if (cmd_source == src_command)
  1172.     {
  1173.         Cvar_SetValue ("_cl_color", playercolor);
  1174.         if (cls.state == ca_connected)
  1175.             Cmd_ForwardToServer ();
  1176.         return;
  1177.     }
  1178.  
  1179.     host_client->colors = playercolor;
  1180.     host_client->edict->v.team = bottom + 1;
  1181.  
  1182. // send notification to all clients
  1183.     MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
  1184.     MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
  1185.     MSG_WriteByte (&sv.reliable_datagram, host_client->colors);
  1186. }
  1187.  
  1188. /*
  1189. ==================
  1190. Host_Kill_f
  1191. ==================
  1192. */
  1193. void Host_Kill_f (void)
  1194. {
  1195.     if (cmd_source == src_command)
  1196.     {
  1197.         Cmd_ForwardToServer ();
  1198.         return;
  1199.     }
  1200.  
  1201.     if (sv_player->v.health <= 0)
  1202.     {
  1203.         SV_ClientPrintf ("Can't suicide -- allready dead!\n");
  1204.         return;
  1205.     }
  1206.     
  1207.     pr_global_struct->time = sv.time;
  1208.     pr_global_struct->self = EDICT_TO_PROG(sv_player);
  1209.     PR_ExecuteProgram (pr_global_struct->ClientKill);
  1210. }
  1211.  
  1212.  
  1213. /*
  1214. ==================
  1215. Host_Pause_f
  1216. ==================
  1217. */
  1218. void Host_Pause_f (void)
  1219. {
  1220.     
  1221.     if (cmd_source == src_command)
  1222.     {
  1223.         Cmd_ForwardToServer ();
  1224.         return;
  1225.     }
  1226.     if (!pausable.value)
  1227.         SV_ClientPrintf ("Pause not allowed.\n");
  1228.     else
  1229.     {
  1230.         sv.paused ^= 1;
  1231.  
  1232.         if (sv.paused)
  1233.         {
  1234.             SV_BroadcastPrintf ("%s paused the game\n", pr_strings + sv_player->v.netname);
  1235.         }
  1236.         else
  1237.         {
  1238.             SV_BroadcastPrintf ("%s unpaused the game\n",pr_strings + sv_player->v.netname);
  1239.         }
  1240.  
  1241.     // send notification to all clients
  1242.         MSG_WriteByte (&sv.reliable_datagram, svc_setpause);
  1243.         MSG_WriteByte (&sv.reliable_datagram, sv.paused);
  1244.     }
  1245. }
  1246.  
  1247. //===========================================================================
  1248.  
  1249.  
  1250. /*
  1251. ==================
  1252. Host_PreSpawn_f
  1253. ==================
  1254. */
  1255. void Host_PreSpawn_f (void)
  1256. {
  1257.     if (cmd_source == src_command)
  1258.     {
  1259.         Con_Printf ("prespawn is not valid from the console\n");
  1260.         return;
  1261.     }
  1262.  
  1263.     if (host_client->spawned)
  1264.     {
  1265.         Con_Printf ("prespawn not valid -- allready spawned\n");
  1266.         return;
  1267.     }
  1268.     
  1269.     SZ_Write (&host_client->message, sv.signon.data, sv.signon.cursize);
  1270.     MSG_WriteByte (&host_client->message, svc_signonnum);
  1271.     MSG_WriteByte (&host_client->message, 2);
  1272.     host_client->sendsignon = true;
  1273. }
  1274.  
  1275. /*
  1276. ==================
  1277. Host_Spawn_f
  1278. ==================
  1279. */
  1280. void Host_Spawn_f (void)
  1281. {
  1282.     int        i;
  1283.     client_t    *client;
  1284.     edict_t    *ent;
  1285.  
  1286.     if (cmd_source == src_command)
  1287.     {
  1288.         Con_Printf ("spawn is not valid from the console\n");
  1289.         return;
  1290.     }
  1291.  
  1292.     if (host_client->spawned)
  1293.     {
  1294.         Con_Printf ("Spawn not valid -- allready spawned\n");
  1295.         return;
  1296.     }
  1297.  
  1298. // run the entrance script
  1299.     if (sv.loadgame)
  1300.     {    // loaded games are fully inited allready
  1301.         // if this is the last client to be connected, unpause
  1302.         sv.paused = false;
  1303.     }
  1304.     else
  1305.     {
  1306.         // set up the edict
  1307.         ent = host_client->edict;
  1308.  
  1309.         memset (&ent->v, 0, progs->entityfields * 4);
  1310.         ent->v.colormap = NUM_FOR_EDICT(ent);
  1311.         ent->v.team = (host_client->colors & 15) + 1;
  1312.         ent->v.netname = host_client->name - pr_strings;
  1313.  
  1314.         // copy spawn parms out of the client_t
  1315.  
  1316.         for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
  1317.             (&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
  1318.  
  1319.         // call the spawn function
  1320.  
  1321.         pr_global_struct->time = sv.time;
  1322.         pr_global_struct->self = EDICT_TO_PROG(sv_player);
  1323.         PR_ExecuteProgram (pr_global_struct->ClientConnect);
  1324.  
  1325.         if ((Sys_FloatTime() - host_client->netconnection->connecttime) <= sv.time)
  1326.             Sys_Printf ("%s entered the game\n", host_client->name);
  1327.  
  1328.         PR_ExecuteProgram (pr_global_struct->PutClientInServer);    
  1329.     }
  1330.  
  1331.  
  1332. // send all current names, colors, and frag counts
  1333.     SZ_Clear (&host_client->message);
  1334.  
  1335. // send time of update
  1336.     MSG_WriteByte (&host_client->message, svc_time);
  1337.     MSG_WriteFloat (&host_client->message, sv.time);
  1338.  
  1339.     for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
  1340.     {
  1341.         MSG_WriteByte (&host_client->message, svc_updatename);
  1342.         MSG_WriteByte (&host_client->message, i);
  1343.         MSG_WriteString (&host_client->message, client->name);
  1344.         MSG_WriteByte (&host_client->message, svc_updatefrags);
  1345.         MSG_WriteByte (&host_client->message, i);
  1346.         MSG_WriteShort (&host_client->message, client->old_frags);
  1347.         MSG_WriteByte (&host_client->message, svc_updatecolors);
  1348.         MSG_WriteByte (&host_client->message, i);
  1349.         MSG_WriteByte (&host_client->message, client->colors);
  1350.     }
  1351.     
  1352. // send all current light styles
  1353.     for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
  1354.     {
  1355.         MSG_WriteByte (&host_client->message, svc_lightstyle);
  1356.         MSG_WriteByte (&host_client->message, (char)i);
  1357.         MSG_WriteString (&host_client->message, sv.lightstyles[i]);
  1358.     }
  1359.  
  1360. //
  1361. // send some stats
  1362. //
  1363.     MSG_WriteByte (&host_client->message, svc_updatestat);
  1364.     MSG_WriteByte (&host_client->message, STAT_TOTALSECRETS);
  1365.     MSG_WriteLong (&host_client->message, pr_global_struct->total_secrets);
  1366.  
  1367.     MSG_WriteByte (&host_client->message, svc_updatestat);
  1368.     MSG_WriteByte (&host_client->message, STAT_TOTALMONSTERS);
  1369.     MSG_WriteLong (&host_client->message, pr_global_struct->total_monsters);
  1370.  
  1371.     MSG_WriteByte (&host_client->message, svc_updatestat);
  1372.     MSG_WriteByte (&host_client->message, STAT_SECRETS);
  1373.     MSG_WriteLong (&host_client->message, pr_global_struct->found_secrets);
  1374.  
  1375.     MSG_WriteByte (&host_client->message, svc_updatestat);
  1376.     MSG_WriteByte (&host_client->message, STAT_MONSTERS);
  1377.     MSG_WriteLong (&host_client->message, pr_global_struct->killed_monsters);
  1378.  
  1379.     
  1380. //
  1381. // send a fixangle
  1382. // Never send a roll angle, because savegames can catch the server
  1383. // in a state where it is expecting the client to correct the angle
  1384. // and it won't happen if the game was just loaded, so you wind up
  1385. // with a permanent head tilt
  1386.     ent = EDICT_NUM( 1 + (host_client - svs.clients) );
  1387.     MSG_WriteByte (&host_client->message, svc_setangle);
  1388.     for (i=0 ; i < 2 ; i++)
  1389.         MSG_WriteAngle (&host_client->message, ent->v.angles[i] );
  1390.     MSG_WriteAngle (&host_client->message, 0 );
  1391.  
  1392.     SV_WriteClientdataToMessage (sv_player, &host_client->message);
  1393.  
  1394.     MSG_WriteByte (&host_client->message, svc_signonnum);
  1395.     MSG_WriteByte (&host_client->message, 3);
  1396.     host_client->sendsignon = true;
  1397. }
  1398.  
  1399. /*
  1400. ==================
  1401. Host_Begin_f
  1402. ==================
  1403. */
  1404. void Host_Begin_f (void)
  1405. {
  1406.     if (cmd_source == src_command)
  1407.     {
  1408.         Con_Printf ("begin is not valid from the console\n");
  1409.         return;
  1410.     }
  1411.  
  1412.     host_client->spawned = true;
  1413. }
  1414.  
  1415. //===========================================================================
  1416.  
  1417.  
  1418. /*
  1419. ==================
  1420. Host_Kick_f
  1421.  
  1422. Kicks a user off of the server
  1423. ==================
  1424. */
  1425. void Host_Kick_f (void)
  1426. {
  1427.     char        *who;
  1428.     char        *message = NULL;
  1429.     client_t    *save;
  1430.     int            i;
  1431.     qboolean    byNumber = false;
  1432.  
  1433.     if (cmd_source == src_command)
  1434.     {
  1435.         if (!sv.active)
  1436.         {
  1437.             Cmd_ForwardToServer ();
  1438.             return;
  1439.         }
  1440.     }
  1441.     else if (pr_global_struct->deathmatch && !host_client->privileged)
  1442.         return;
  1443.  
  1444.     save = host_client;
  1445.  
  1446.     if (Cmd_Argc() > 2 && Q_strcmp(Cmd_Argv(1), "#") == 0)
  1447.     {
  1448.         i = Q_atof(Cmd_Argv(2)) - 1;
  1449.         if (i < 0 || i >= svs.maxclients)
  1450.             return;
  1451.         if (!svs.clients[i].active)
  1452.             return;
  1453.         host_client = &svs.clients[i];
  1454.         byNumber = true;
  1455.     }
  1456.     else
  1457.     {
  1458.         for (i = 0, host_client = svs.clients; i < svs.maxclients; i++, host_client++)
  1459.         {
  1460.             if (!host_client->active)
  1461.                 continue;
  1462.             if (Q_strcasecmp(host_client->name, Cmd_Argv(1)) == 0)
  1463.                 break;
  1464.         }
  1465.     }
  1466.  
  1467.     if (i < svs.maxclients)
  1468.     {
  1469.         if (cmd_source == src_command)
  1470.             if (cls.state == ca_dedicated)
  1471.                 who = "Console";
  1472.             else
  1473.                 who = cl_name.string;
  1474.         else
  1475.             who = save->name;
  1476.  
  1477.         // can't kick yourself!
  1478.         if (host_client == save)
  1479.             return;
  1480.  
  1481.         if (Cmd_Argc() > 2)
  1482.         {
  1483.             message = COM_Parse(Cmd_Args());
  1484.             if (byNumber)
  1485.             {
  1486.                 message++;                            // skip the #
  1487.                 while (*message == ' ')                // skip white space
  1488.                     message++;
  1489.                 message += Q_strlen(Cmd_Argv(2));    // skip the number
  1490.             }
  1491.             while (*message && *message == ' ')
  1492.                 message++;
  1493.         }
  1494.         if (message)
  1495.             SV_ClientPrintf ("Kicked by %s: %s\n", who, message);
  1496.         else
  1497.             SV_ClientPrintf ("Kicked by %s\n", who);
  1498.         SV_DropClient (false);
  1499.     }
  1500.  
  1501.     host_client = save;
  1502. }
  1503.  
  1504. /*
  1505. ===============================================================================
  1506.  
  1507. DEBUGGING TOOLS
  1508.  
  1509. ===============================================================================
  1510. */
  1511.  
  1512. /*
  1513. ==================
  1514. Host_Give_f
  1515. ==================
  1516. */
  1517. void Host_Give_f (void)
  1518. {
  1519.     char    *t;
  1520.     int        v, w;
  1521.     eval_t    *val;
  1522.  
  1523.     if (cmd_source == src_command)
  1524.     {
  1525.         Cmd_ForwardToServer ();
  1526.         return;
  1527.     }
  1528.  
  1529.     if (pr_global_struct->deathmatch && !host_client->privileged)
  1530.         return;
  1531.  
  1532.     t = Cmd_Argv(1);
  1533.     v = atoi (Cmd_Argv(2));
  1534.     
  1535.     switch (t[0])
  1536.     {
  1537.    case '0':
  1538.    case '1':
  1539.    case '2':
  1540.    case '3':
  1541.    case '4':
  1542.    case '5':
  1543.    case '6':
  1544.    case '7':
  1545.    case '8':
  1546.    case '9':
  1547.       // MED 01/04/97 added hipnotic give stuff
  1548.       if (hipnotic)
  1549.       {
  1550.          if (t[0] == '6')
  1551.          {
  1552.             if (t[1] == 'a')
  1553.                sv_player->v.items = (int)sv_player->v.items | HIT_PROXIMITY_GUN;
  1554.             else
  1555.                sv_player->v.items = (int)sv_player->v.items | IT_GRENADE_LAUNCHER;
  1556.          }
  1557.          else if (t[0] == '9')
  1558.             sv_player->v.items = (int)sv_player->v.items | HIT_LASER_CANNON;
  1559.          else if (t[0] == '0')
  1560.             sv_player->v.items = (int)sv_player->v.items | HIT_MJOLNIR;
  1561.          else if (t[0] >= '2')
  1562.             sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
  1563.       }
  1564.       else
  1565.       {
  1566.          if (t[0] >= '2')
  1567.             sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
  1568.       }
  1569.         break;
  1570.     
  1571.     case 's':
  1572.         if (rogue)
  1573.         {
  1574.             val = GetEdictFieldValue(sv_player, "ammo_shells1");
  1575.             if (val)
  1576.                 val->_float = v;
  1577.         }
  1578.  
  1579.         sv_player->v.ammo_shells = v;
  1580.         break;        
  1581.     case 'n':
  1582.         if (rogue)
  1583.         {
  1584.             val = GetEdictFieldValue(sv_player, "ammo_nails1");
  1585.             if (val)
  1586.             {
  1587.                 val->_float = v;
  1588.                 if (sv_player->v.weapon <= IT_LIGHTNING)
  1589.                     sv_player->v.ammo_nails = v;
  1590.             }
  1591.         }
  1592.         else
  1593.         {
  1594.             sv_player->v.ammo_nails = v;
  1595.         }
  1596.         break;        
  1597.     case 'l':
  1598.         if (rogue)
  1599.         {
  1600.             val = GetEdictFieldValue(sv_player, "ammo_lava_nails");
  1601.             if (val)
  1602.             {
  1603.                 val->_float = v;
  1604.                 if (sv_player->v.weapon > IT_LIGHTNING)
  1605.                     sv_player->v.ammo_nails = v;
  1606.             }
  1607.         }
  1608.         break;
  1609.     case 'r':
  1610.         if (rogue)
  1611.         {
  1612.             val = GetEdictFieldValue(sv_player, "ammo_rockets1");
  1613.             if (val)
  1614.             {
  1615.                 val->_float = v;
  1616.                 if (sv_player->v.weapon <= IT_LIGHTNING)
  1617.                     sv_player->v.ammo_rockets = v;
  1618.             }
  1619.         }
  1620.         else
  1621.         {
  1622.             sv_player->v.ammo_rockets = v;
  1623.         }
  1624.         break;        
  1625.     case 'm':
  1626.         if (rogue)
  1627.         {
  1628.             val = GetEdictFieldValue(sv_player, "ammo_multi_rockets");
  1629.             if (val)
  1630.             {
  1631.                 val->_float = v;
  1632.                 if (sv_player->v.weapon > IT_LIGHTNING)
  1633.                     sv_player->v.ammo_rockets = v;
  1634.             }
  1635.         }
  1636.         break;        
  1637.     case 'h':
  1638.         sv_player->v.health = v;
  1639.         break;        
  1640.     case 'c':
  1641.         if (rogue)
  1642.         {
  1643.             val = GetEdictFieldValue(sv_player, "ammo_cells1");
  1644.             if (val)
  1645.             {
  1646.                 val->_float = v;
  1647.                 if (sv_player->v.weapon <= IT_LIGHTNING)
  1648.                     sv_player->v.ammo_cells = v;
  1649.             }
  1650.         }
  1651.         else
  1652.         {
  1653.             sv_player->v.ammo_cells = v;
  1654.         }
  1655.         break;        
  1656.     case 'p':
  1657.         if (rogue)
  1658.         {
  1659.             val = GetEdictFieldValue(sv_player, "ammo_plasma");
  1660.             if (val)
  1661.             {
  1662.                 val->_float = v;
  1663.                 if (sv_player->v.weapon > IT_LIGHTNING)
  1664.                     sv_player->v.ammo_cells = v;
  1665.             }
  1666.         }
  1667.         break;        
  1668.     }
  1669. }
  1670.  
  1671. edict_t    *FindViewthing (void)
  1672. {
  1673.     int        i;
  1674.     edict_t    *e;
  1675.     
  1676.     for (i=0 ; i<sv.num_edicts ; i++)
  1677.     {
  1678.         e = EDICT_NUM(i);
  1679.         if ( !strcmp (pr_strings + e->v.classname, "viewthing") )
  1680.             return e;
  1681.     }
  1682.     Con_Printf ("No viewthing on map\n");
  1683.     return NULL;
  1684. }
  1685.  
  1686. /*
  1687. ==================
  1688. Host_Viewmodel_f
  1689. ==================
  1690. */
  1691. void Host_Viewmodel_f (void)
  1692. {
  1693.     edict_t    *e;
  1694.     model_t    *m;
  1695.  
  1696.     e = FindViewthing ();
  1697.     if (!e)
  1698.         return;
  1699.  
  1700.     m = Mod_ForName (Cmd_Argv(1), false);
  1701.     if (!m)
  1702.     {
  1703.         Con_Printf ("Can't load %s\n", Cmd_Argv(1));
  1704.         return;
  1705.     }
  1706.     
  1707.     e->v.frame = 0;
  1708.     cl.model_precache[(int)e->v.modelindex] = m;
  1709. }
  1710.  
  1711. /*
  1712. ==================
  1713. Host_Viewframe_f
  1714. ==================
  1715. */
  1716. void Host_Viewframe_f (void)
  1717. {
  1718.     edict_t    *e;
  1719.     int        f;
  1720.     model_t    *m;
  1721.  
  1722.     e = FindViewthing ();
  1723.     if (!e)
  1724.         return;
  1725.     m = cl.model_precache[(int)e->v.modelindex];
  1726.  
  1727.     f = atoi(Cmd_Argv(1));
  1728.     if (f >= m->numframes)
  1729.         f = m->numframes-1;
  1730.  
  1731.     e->v.frame = f;        
  1732. }
  1733.  
  1734.  
  1735. void PrintFrameName (model_t *m, int frame)
  1736. {
  1737.     aliashdr_t             *hdr;
  1738.     maliasframedesc_t    *pframedesc;
  1739.  
  1740.     hdr = (aliashdr_t *)Mod_Extradata (m);
  1741.     if (!hdr)
  1742.         return;
  1743.     pframedesc = &hdr->frames[frame];
  1744.     
  1745.     Con_Printf ("frame %i: %s\n", frame, pframedesc->name);
  1746. }
  1747.  
  1748. /*
  1749. ==================
  1750. Host_Viewnext_f
  1751. ==================
  1752. */
  1753. void Host_Viewnext_f (void)
  1754. {
  1755.     edict_t    *e;
  1756.     model_t    *m;
  1757.     
  1758.     e = FindViewthing ();
  1759.     if (!e)
  1760.         return;
  1761.     m = cl.model_precache[(int)e->v.modelindex];
  1762.  
  1763.     e->v.frame = e->v.frame + 1;
  1764.     if (e->v.frame >= m->numframes)
  1765.         e->v.frame = m->numframes - 1;
  1766.  
  1767.     PrintFrameName (m, e->v.frame);        
  1768. }
  1769.  
  1770. /*
  1771. ==================
  1772. Host_Viewprev_f
  1773. ==================
  1774. */
  1775. void Host_Viewprev_f (void)
  1776. {
  1777.     edict_t    *e;
  1778.     model_t    *m;
  1779.  
  1780.     e = FindViewthing ();
  1781.     if (!e)
  1782.         return;
  1783.  
  1784.     m = cl.model_precache[(int)e->v.modelindex];
  1785.  
  1786.     e->v.frame = e->v.frame - 1;
  1787.     if (e->v.frame < 0)
  1788.         e->v.frame = 0;
  1789.  
  1790.     PrintFrameName (m, e->v.frame);        
  1791. }
  1792.  
  1793. /*
  1794. ===============================================================================
  1795.  
  1796. DEMO LOOP CONTROL
  1797.  
  1798. ===============================================================================
  1799. */
  1800.  
  1801.  
  1802. /*
  1803. ==================
  1804. Host_Startdemos_f
  1805. ==================
  1806. */
  1807. void Host_Startdemos_f (void)
  1808. {
  1809.     int        i, c;
  1810.  
  1811.     if (cls.state == ca_dedicated)
  1812.     {
  1813.         if (!sv.active)
  1814.             Cbuf_AddText ("map start\n");
  1815.         return;
  1816.     }
  1817.  
  1818.     c = Cmd_Argc() - 1;
  1819.     if (c > MAX_DEMOS)
  1820.     {
  1821.         Con_Printf ("Max %i demos in demoloop\n", MAX_DEMOS);
  1822.         c = MAX_DEMOS;
  1823.     }
  1824.     Con_Printf ("%i demo(s) in loop\n", c);
  1825.  
  1826.     for (i=1 ; i<c+1 ; i++)
  1827.         strncpy (cls.demos[i-1], Cmd_Argv(i), sizeof(cls.demos[0])-1);
  1828.  
  1829.     if (!sv.active && cls.demonum != -1 && !cls.demoplayback)
  1830.     {
  1831.         cls.demonum = 0;
  1832.         CL_NextDemo ();
  1833.     }
  1834.     else
  1835.         cls.demonum = -1;
  1836. }
  1837.  
  1838.  
  1839. /*
  1840. ==================
  1841. Host_Demos_f
  1842.  
  1843. Return to looping demos
  1844. ==================
  1845. */
  1846. void Host_Demos_f (void)
  1847. {
  1848.     if (cls.state == ca_dedicated)
  1849.         return;
  1850.     if (cls.demonum == -1)
  1851.         cls.demonum = 1;
  1852.     CL_Disconnect_f ();
  1853.     CL_NextDemo ();
  1854. }
  1855.  
  1856. /*
  1857. ==================
  1858. Host_Stopdemo_f
  1859.  
  1860. Return to looping demos
  1861. ==================
  1862. */
  1863. void Host_Stopdemo_f (void)
  1864. {
  1865.     if (cls.state == ca_dedicated)
  1866.         return;
  1867.     if (!cls.demoplayback)
  1868.         return;
  1869.     CL_StopPlayback ();
  1870.     CL_Disconnect ();
  1871. }
  1872.  
  1873. //=============================================================================
  1874.  
  1875. /*
  1876. ==================
  1877. Host_InitCommands
  1878. ==================
  1879. */
  1880. void Host_InitCommands (void)
  1881. {
  1882.     Cmd_AddCommand ("status", Host_Status_f);
  1883.     Cmd_AddCommand ("quit", Host_Quit_f);
  1884.     Cmd_AddCommand ("god", Host_God_f);
  1885.     Cmd_AddCommand ("notarget", Host_Notarget_f);
  1886.     Cmd_AddCommand ("fly", Host_Fly_f);
  1887.     Cmd_AddCommand ("map", Host_Map_f);
  1888.     Cmd_AddCommand ("restart", Host_Restart_f);
  1889.     Cmd_AddCommand ("changelevel", Host_Changelevel_f);
  1890. #ifdef QUAKE2
  1891.     Cmd_AddCommand ("changelevel2", Host_Changelevel2_f);
  1892. #endif
  1893.     Cmd_AddCommand ("connect", Host_Connect_f);
  1894.     Cmd_AddCommand ("reconnect", Host_Reconnect_f);
  1895.     Cmd_AddCommand ("name", Host_Name_f);
  1896.     Cmd_AddCommand ("noclip", Host_Noclip_f);
  1897.     Cmd_AddCommand ("version", Host_Version_f);
  1898. #ifdef IDGODS
  1899.     Cmd_AddCommand ("please", Host_Please_f);
  1900. #endif
  1901.     Cmd_AddCommand ("say", Host_Say_f);
  1902.     Cmd_AddCommand ("say_team", Host_Say_Team_f);
  1903.     Cmd_AddCommand ("tell", Host_Tell_f);
  1904.     Cmd_AddCommand ("color", Host_Color_f);
  1905.     Cmd_AddCommand ("kill", Host_Kill_f);
  1906.     Cmd_AddCommand ("pause", Host_Pause_f);
  1907.     Cmd_AddCommand ("spawn", Host_Spawn_f);
  1908.     Cmd_AddCommand ("begin", Host_Begin_f);
  1909.     Cmd_AddCommand ("prespawn", Host_PreSpawn_f);
  1910.     Cmd_AddCommand ("kick", Host_Kick_f);
  1911.     Cmd_AddCommand ("ping", Host_Ping_f);
  1912.     Cmd_AddCommand ("load", Host_Loadgame_f);
  1913.     Cmd_AddCommand ("save", Host_Savegame_f);
  1914.     Cmd_AddCommand ("give", Host_Give_f);
  1915.  
  1916.     Cmd_AddCommand ("startdemos", Host_Startdemos_f);
  1917.     Cmd_AddCommand ("demos", Host_Demos_f);
  1918.     Cmd_AddCommand ("stopdemo", Host_Stopdemo_f);
  1919.  
  1920.     Cmd_AddCommand ("viewmodel", Host_Viewmodel_f);
  1921.     Cmd_AddCommand ("viewframe", Host_Viewframe_f);
  1922.     Cmd_AddCommand ("viewnext", Host_Viewnext_f);
  1923.     Cmd_AddCommand ("viewprev", Host_Viewprev_f);
  1924.  
  1925.     Cmd_AddCommand ("mcache", Mod_Print);
  1926. }
  1927.